package org.github.core.spring.exception;

import cn.dev33.satoken.exception.SaTokenException;
import cn.hutool.core.lang.Pair;
import com.github.houbb.validator.api.api.constraint.IConstraintResult;
import com.github.houbb.validator.api.api.result.IResult;
import lombok.extern.slf4j.Slf4j;
import org.github.core.exception.ClientException;
import org.github.core.exception.RemoteException;
import org.github.core.exception.ServerException;
import org.github.core.exception.ValidException;
import org.github.core.satoken.SaTokenExceptionConverter;
import org.github.core.spring.restful.Base;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.util.NestedServletException;
import static cn.hutool.core.collection.CollUtil.getFirst;
import static org.github.core.spring.util.MessageSourceUtil.i18n;
import static org.springframework.http.HttpStatus.BAD_REQUEST;
import static org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR;

@Slf4j
public abstract class ExceptionConverter {
  public static Pair<Base,Boolean> convert(Throwable ex) {
    if (ex instanceof ValidException e) {
      IResult           result = e.getResult();
      IConstraintResult first  = getFirst(result.notPassList());
      String            msg    = i18n(first.message());
      return Pair.of(Base.of(BAD_REQUEST, msg), false);
    }
    if (ex instanceof ClientException e) {
      String msg = i18n(ex.getMessage(), e.getArgs());
      return Pair.of(Base.of(BAD_REQUEST, msg), false);
    }
    if (ex instanceof ServerException e) {
      String msg = i18n(ex.getMessage(), e.getArgs());
      return Pair.of(Base.of(INTERNAL_SERVER_ERROR, msg), false);
    }
    if (ex instanceof RemoteException e) {
      return Pair.of(e.getData(), false);
    }

    if (ex instanceof SaTokenException) {
      return SaTokenExceptionConverter.convert(((SaTokenException) ex));
    }

    if (ex instanceof NestedServletException) {
      if (ex.getCause() != null) {
        return convert(ex.getCause());
      }
    }
    if (ex instanceof HttpRequestMethodNotSupportedException e) {
      //TODO
      return Pair.of(Base.of(BAD_REQUEST, e.getMessage()), false);
    }
    if (ex instanceof ResponseStatusException) {
      HttpStatus status = ((ResponseStatusException) ex).getStatus();
      return Pair.of(Base.of(status, null), status == INTERNAL_SERVER_ERROR);
    }

    log.error(ex.getMessage(), ex);
    String msg = i18n("system.error");
    return Pair.of(Base.of(INTERNAL_SERVER_ERROR, msg), true);
  }
}
